package com.example.clsj.anno;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.date.TimeInterval;
import cn.hutool.json.JSONUtil;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;

@Aspect
@Component
@Slf4j
public class LoggingAspect {

    @Pointcut("@annotation(com.example.clsj.anno.Loggable)")
    public void loggable() {}

    /**
     * 环绕通知，用于拦截com.example.myspringboot.web包下的所有方法执行，记录方法的执行时间。
     * @param joinPoint 切面连接点，提供目标方法的信息和调用能力。
     * @return 返回目标方法的执行结果。
     * @throws Throwable 如果目标方法执行过程中发生异常，则抛出。
     */
    @Around("loggable()")
    public Object logExecutionTime(ProceedingJoinPoint joinPoint) throws Throwable {
        TimeInterval timer = DateUtil.timer();

        // 记录方法开始执行的时间
        log.info(" started ... ");
        try {
            // 尝试记录请求参数信息
            log.info("request information: {}", JSONUtil.toJsonStr(joinPoint.getArgs()));
        } catch (Exception e) {
            // 如果记录请求参数时发生异常，则记录异常信息
            log.error(e.getMessage(), e);
        }

        // 执行目标方法
        Object result = joinPoint.proceed();

        try {
            // 尝试记录方法返回值信息
            log.info("return information: {}", JSONUtil.toJsonStr(result));
        } catch (Exception e) {
            // 如果记录返回值时发生异常，则记录异常信息
            log.error(e.getMessage(), e);
        }

        // 计算并记录方法执行耗时
        log.info(" completed in " + timer.intervalPretty());

        // 返回目标方法的执行结果
        return result;
    }

}
